package com.tg.appcommon.router;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.tg.appcommon.android.TGApplicationBase;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;

public class TGModuleRouter {
    public static TGModuleRouter getInstance() {
        return InstanceHolder.sInstance;
    }

    private static class InstanceHolder {
        static TGModuleRouter sInstance = new TGModuleRouter();
    }

    private final CopyOnWriteArrayList<IModuleFetcher> mModuleFetchers = new CopyOnWriteArrayList<>();
    public void register(@NonNull IBusinessModule module) {
        register(new SimpleModuleFetcher(module));
    }

    public void register(@NonNull IModuleFetcher fetcher) {
        if (!mModuleFetchers.contains(fetcher)) {
            mModuleFetchers.add(fetcher);
        }
    }

    @Nullable
    public <T extends IBusinessModule> T getBusinessModule(Class<T> clazz) {
        for (IModuleFetcher fetcher : mModuleFetchers) {
            if (fetcher.isa(clazz)) {
                IBusinessModule module = fetcher.getBusinessModule(clazz);
                if (clazz.isInstance(module)) {
                    return clazz.cast(module);
                }
            }
        }
        return null;
    }


    @Nullable
    public <T extends IBusinessModule> List<T> getBusinessModuleList(Class<T> clazz) {
        List<T> list =  new ArrayList<>();
        for (IModuleFetcher fetcher : mModuleFetchers) {
            if (fetcher.isa(clazz)) {
                IBusinessModule module = fetcher.getBusinessModule(clazz);
                if (clazz.isInstance(module)) {
                    list.add(clazz.cast(module));
                }
            }
        }
        return list;
    }

    private TGModuleRouter() {
        TGApplicationBase.getInstance().putGlobalObject(TGModuleRouter.class, this);
    }

    static class SimpleModuleFetcher implements IModuleFetcher {
        IBusinessModule mInstance;

        SimpleModuleFetcher(IBusinessModule instance) {
            mInstance = instance;
        }

        @Override
        public <T extends IBusinessModule> boolean isa(Class<T> clazz) {
            return clazz.isInstance(mInstance);
        }

        @Nullable
        @Override
        public <T extends IBusinessModule> T getBusinessModule(Class<T> clazz) {
            if (clazz.isInstance(mInstance)) {
                return clazz.cast(mInstance);
            }
            return null;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            SimpleModuleFetcher that = (SimpleModuleFetcher) o;
            return Objects.equals(mInstance, that.mInstance);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mInstance);
        }
    }
}
